package com.basker.pisces.core.serialize.xml;

import java.util.Map;

import org.springframework.util.Assert;

import com.basker.pisces.core.meta.ICollectionField;
import com.basker.pisces.core.meta.IDataObjectField;
import com.basker.pisces.core.meta.IDataObjectMeta;
import com.basker.pisces.core.meta.bean.BeanMetaManager;

public class BeanXmlSerializeHandler extends AbstractXmlSerializeHandler {

    private IDataObjectMeta rootMeta;

    public BeanXmlSerializeHandler(Class<?> beanClass) {
        Assert.notNull(beanClass, "parameter 'beanClass' is required");

        this.rootMeta = BeanMetaManager.getBeanMeta(beanClass);
    }

    @Override
    public IDataObjectMeta getDataObjectMeta(String name, Map<String, String> attrs) {
        Assert.hasText(name, "parameter 'name' is required");

        IDataObjectMeta objectMeta = this.findMeta(rootMeta, name);

        if (objectMeta == null) {
            throw new IllegalArgumentException(
                    "DataObjectMeta '" + name + "' not found in '" + this.rootMeta.getName() + "'");
        }

        return objectMeta;

    }

    @Override
    public boolean writeClassName() {
        return false;
    }

    private IDataObjectMeta findMeta(IDataObjectMeta dataObjectMeta, String name) {
        if (dataObjectMeta == null) {
            return null;
        }

        String dataObjectMetaElementName = this.getDataObjectMetaElementName(dataObjectMeta);
        if (dataObjectMetaElementName.equals(name)) {
            return dataObjectMeta;
        }

        for (IDataObjectField field : dataObjectMeta.getDataObjectFields()) {
            IDataObjectMeta refObjectMeta = field.getDataObjectMeta();

            IDataObjectMeta meta = this.findMeta(refObjectMeta, name);
            if (meta != null) {
                return meta;
            }
        }

        for (ICollectionField field : dataObjectMeta.getCollectionFields()) {
            IDataObjectMeta itemObjectMeta = field.getItemObjectMeta();

            IDataObjectMeta meta = this.findMeta(itemObjectMeta, name);
            if (meta != null) {
                return meta;
            }
        }

        return null;
    }

}
